fix(arborist): recognize registry-mediated tarballs - #9921
Open
martinrrm wants to merge 5 commits into
Open
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
martinrrm
commented
Aug 27, 2026
| }) | ||
|
|
||
| t.test('allowRemote=none blocks same-origin tarball outside registry path', async t => { | ||
| t.test('allowRemote=none allows registry-advertised tarball outside registry path', async t => { |
Contributor
Author
There was a problem hiding this comment.
This test for the main change to fix #9796.
If a registry is serving tarballs from a different path than the actual registry metadata (such as https://registry.example.com/blob/package.tgz, while the registry is https://registry.example.com/npm) this results in EALLOWREMOTE attempting to install anything from it.
martinrrm
commented
Aug 27, 2026
| await t.resolves(arb.reify(), 'registry-advertised sibling-path tarball is allowed') | ||
| }) | ||
|
|
||
| t.test('allowRemote=none verifies against dependency identity, not lockfile name', async t => { |
Contributor
Author
There was a problem hiding this comment.
This test is also important; we are now getting the packument of the package (so a new metadata request if the tarball URL is different from the registry) and validating that the advertised URL are the same.
Validate locked versions, preserve root-selected aliases for ordinary consumers, and reuse registry URL evidence with coalesced abbreviated metadata requests. Keep explicit signature and attestation verification separate from captured URL evidence. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Problem
During reification, Arborist passes registry tarballs to pacote as
name@URL. npm-package-arg parses that temporary spec as a remote dependency, so Arborist needs a narrow exemption for registry-mediated tarballs.The existing classifier only recognized tarball paths beneath the configured registry path. Private registries can legitimately advertise tarballs from another path on the same origin. It also selected registries using the installed dependency slot: for
hoek: npm:@npm/hoek@6.1.4, that loses the target scope and can select the wrong registry or credentials. Both cases can incorrectly fail with EALLOWREMOTE under the npm 12 defaultallow-remote=none.Implementation
Package identity and compatibility
Identity comes from valid dependency specifications, not package/lockfile name fields. Aliases are unwrapped to target names. Ordinary peers constrain the installed slot rather than redefining an alias target. Project/workspace selections also take precedence over ordinary compatible transitive requirements, while disagreeing explicit alias targets remain rejected. A transitive alias cannot supersede a plain root selection.
Linked installs carry this identity through intermediate proxies and synthetic store nodes. Extraction uses the target identity independently of remote-permission mode, so authentication follows the target scope while the install location remains the alias slot.
Sibling-path verification
The configured-registry-path fast path remains. A same-origin URL outside that path is permitted only when registry evidence for the trusted package and exact version advertises the same effective tarball URL.
Locked versions must be exact semantic versions; aliases, ranges, tags, URLs, and other dependency specifications in that field cannot redirect verification. Metadata names and versions must match. Host replacement is applied consistently to both URLs. Fragments are ignored; the remaining URL, including path and query, must match.
Metadata reuse and request behavior
Cold locked sibling-path installs can still require metadata requests. A cached tarball alone does not establish the additional evidence needed for an offline sibling-path install. This is an intentional availability/performance tradeoff, not a promise of zero additional requests.
Policy boundaries
Already-permitted implicit/explicit
all, and root-direct requests underroot, skip URL verification. Metadata failures, mismatches, unverifiable identities, and cross-origin URLs do not grant an exemption. Explicit remote dependencies remain governed by the configured policy. Extraction continues to receive the locked integrity value.Regression coverage
Fixes #9796